// Copyright 2025 Laszlo Consulting Kft.
// SPDX-License-Identifier: Apache-2.0

import { createSignal, createEffect, Show, onMount, onCleanup } from "solid-js";
import { type ActiveFilter } from "../components/filterBar/FilterBar.tsx";
import { SettingsModal } from "../components/settings/SettingsModal.tsx";
import { applyTheme, loadInitialTheme, type ThemeName } from "../utils/theme.ts";
import { ShortcutPrefix, getShortcutPrefix, getDefaultShortcutPrefix, setShortcutPrefix, formatShortcutForDisplay } from "../utils/shortcuts.ts";
import { useApiResourceStore } from "../store/apiResourceStore.tsx";
import { useErrorStore } from "../store/errorStore.tsx";
import { PaneManager } from "../components/paneManager/index.ts";
import { DashboardPaneWithProvider } from "../components/DashboardPane.tsx";
import type { PaneNode } from "../components/paneManager/PaneManager.tsx";
import type { Orientation } from "../components/paneManager/PaneManager.tsx";

// Persist within this module (component-local across route changes)
let savedPaneTree: PaneNode | undefined = undefined;
let savedPaneSizes: Record<string, number[]> = {};
let savedActivePaneKey: number | undefined = undefined;
const savedPaneFilters = new Map<number, ActiveFilter[]>();

// URL sync helpers for shareable multi-pane state
type EncodedPaneState = {
  t: PaneNode;
  s: Record<string, number[]>;
  a: number;
  f: Array<{ k: number; fl: ActiveFilter[] }>;
};

function encodePaneStateForUrl(tree: PaneNode, sizes: Record<string, number[]>, activeKey: number, filters: Map<number, ActiveFilter[]>): string | undefined {
  try {
    const filterArray = Array.from(filters.entries()).map(([k, fl]) => ({ k, fl }));
    const minimal: EncodedPaneState = { t: tree, s: sizes, a: activeKey, f: filterArray };
    const json = JSON.stringify(minimal);
    // Use base64 for compactness; safely encode UTF-8
    const b64 = globalThis.btoa(unescape(encodeURIComponent(json)));
    return b64;
  } catch {
    return undefined;
  }
}

function decodePaneStateFromUrl(b64: string): EncodedPaneState | undefined {
  try {
    const json = decodeURIComponent(escape(globalThis.atob(b64)));
    const parsed = JSON.parse(json);
    if (!parsed || typeof parsed !== 'object') return undefined;
    if (!parsed.t || !parsed.s || typeof parsed.a !== 'number' || !Array.isArray(parsed.f)) return undefined;
    return parsed as EncodedPaneState;
  } catch {
    return undefined;
  }
}

function tryReadPaneStateFromUrl(): void {
  try {
    const url = new URL(globalThis.location.href);
    const encoded = url.searchParams.get('ps');
    if (!encoded) return;
    const state = decodePaneStateFromUrl(encoded);
    if (!state) return;
    savedPaneTree = state.t;
    savedPaneSizes = state.s || {};
    savedActivePaneKey = state.a;
    savedPaneFilters.clear();
    for (const entry of state.f) {
      if (entry && typeof entry.k === 'number' && Array.isArray(entry.fl)) {
        savedPaneFilters.set(entry.k, entry.fl);
      }
    }
  } catch {
    // ignore malformed URL state
  }
}

function writePaneStateToUrl(): void {
  try {
    if (!savedPaneTree || savedActivePaneKey === undefined) return;
    const encoded = encodePaneStateForUrl(savedPaneTree, savedPaneSizes, savedActivePaneKey, savedPaneFilters);
    if (!encoded) return;
    const url = new URL(globalThis.location.href);
    url.searchParams.set('ps', encoded);
    globalThis.history.replaceState(null, '', url.toString());
  } catch {
    // noop
  }
}

export function Dashboard() {
  const apiResourceStore = useApiResourceStore();
  const errorStore = useErrorStore();
  
  // Header / settings
  const [contextMenuOpen, setContextMenuOpen] = createSignal(false);
  const [settingsOpen, setSettingsOpen] = createSignal(false);
  const [theme, setTheme] = createSignal<ThemeName>(loadInitialTheme());
  const [viewShortcutModifier, setViewShortcutModifier] = createSignal<ShortcutPrefix>(
    typeof globalThis !== 'undefined' ? getShortcutPrefix() : getDefaultShortcutPrefix()
  );
  
  let contextDropdownRef: HTMLDivElement | undefined;

  // Watch status in header - updated by PaneManager
  const [watchStatus, setWatchStatus] = createSignal("●");
  
  // Attempt to restore pane state from URL (only once per load)
  tryReadPaneStateFromUrl();
  
  // Cache of pane filter states - updated by providers, used to restore state after tree changes
  const paneFilterCache = new Map<number, ActiveFilter[]>(savedPaneFilters);
  
  // Update cache when pane filters change
  const handlePaneFilterChange = (paneKey: number, filters: ActiveFilter[]) => {
    paneFilterCache.set(paneKey, filters);
    savedPaneFilters.set(paneKey, filters);
    writePaneStateToUrl();
  };

  // Function to switch to a new context
  const handleContextSwitch = async (contextName: string) => {
    if (contextName === apiResourceStore.contextInfo?.current) {
      setContextMenuOpen(false);
      return;
    }
    
    try {
      await apiResourceStore.switchContext(contextName);
      setContextMenuOpen(false);
    } catch (error) {
      console.error("Error switching context in dashboard:", error);
      
      // Show error to user when context switch fails
      const errorMessage = error instanceof Error ? error.message : 'Failed to switch context';
      console.log('Processing context switch error:', errorMessage);
      errorStore.setApiError(`Context switch failed: ${errorMessage}`);
      setContextMenuOpen(false);
    }
  };
  
  // Handle clicks outside the context dropdown
  const handleOutsideClick = (e: MouseEvent) => {
    if (contextDropdownRef && !contextDropdownRef.contains(e.target as Node)) {
      setContextMenuOpen(false);
    }
  };
  
  onMount(() => {
    document.addEventListener('mousedown', handleOutsideClick);
    applyTheme(theme());
  });
  
  onCleanup(() => {
    document.removeEventListener('mousedown', handleOutsideClick);
  });

  createEffect(() => {
    setShortcutPrefix(viewShortcutModifier());
  });

  return (
    <div class="layout">
      <main class="main-content">
        <div class="header-section">
          {/* Context display on the left */}
          <Show when={apiResourceStore.contextInfo}>
            <div class="context-dropdown" ref={contextDropdownRef}>
              <div 
                class="context-display" 
                onClick={() => setContextMenuOpen(!contextMenuOpen())}
              >
                <span class="context-label">Current Context:</span>
                <span class="context-name">{apiResourceStore.contextInfo?.current}</span>
                <span class="context-dropdown-arrow">▼</span>
                <Show when={watchStatus}>
                  <span
                    classList={{ 
                      "watch-status": true, 
                      "error": watchStatus() !== "●" 
                    }}
                  >
                    {watchStatus()}
                  </span>
                </Show>
              </div>
              
              <Show when={contextMenuOpen()}>
                <div class="context-menu">
                  {apiResourceStore.contextInfo?.contexts.map(context => (
                    <div 
                      class={`context-menu-item ${context.isCurrent ? 'active' : ''}`}
                      onClick={() => handleContextSwitch(context.name)}
                    >
                      <span class="context-menu-name">{context.name}</span>
                      {context.clusterName && (
                        <span class="context-menu-details">
                          Cluster: {context.clusterName}
                        </span>
                      )}
                    </div>
                  ))}
                </div>
              </Show>
            </div>
          </Show>
          
          {/* Right-aligned settings button */}
        <div style={{ "flex-grow": 1 }} />
          <button type="button" class="settings-button" title="Settings" onClick={() => setSettingsOpen(true)}>⚙︎</button>
        </div>

        <Show when={settingsOpen()}>
          <SettingsModal
            open
            onClose={() => setSettingsOpen(false)}
            theme={theme()}
            onChangeTheme={(t) => { setTheme(t); applyTheme(t); }}
            viewShortcutModifier={viewShortcutModifier()}
            onChangeViewShortcutModifier={(m) => setViewShortcutModifier(m as ShortcutPrefix)}
          />
        </Show>

        {/* Panes container */}
        <PaneManager
          initialTree={savedPaneTree ?? { type: 'pane', key: 0 }}
          initialSizes={savedPaneSizes}
          initialActivePaneKey={savedActivePaneKey ?? 0}
          onStatusChange={setWatchStatus}
          onTreeChange={(t) => { savedPaneTree = t; writePaneStateToUrl(); }}
          onSizesChange={(s) => { savedPaneSizes = s; writePaneStateToUrl(); }}
          onActivePaneChange={(k) => { savedActivePaneKey = k; writePaneStateToUrl(); }}
          onPaneSplit={(originalPaneKey: number, newPaneKey: number, _orientation: Orientation) => {
            const existing = paneFilterCache.get(originalPaneKey);
            if (existing && Array.isArray(existing)) {
              const copy = existing.map(f => ({ ...f }));
              paneFilterCache.set(newPaneKey, copy);
              savedPaneFilters.set(newPaneKey, copy);
              writePaneStateToUrl();
            }
          }}
          renderPane={(paneProps) => (
            <DashboardPaneWithProvider
              paneKey={paneProps.paneKey}
              focused={paneProps.focused}
              onFocus={paneProps.onFocus}
              onStatusChange={paneProps.onStatusChange}
              onSplit={paneProps.onSplit}
              onClose={paneProps.onClose}
              paneFilterCache={paneFilterCache}
              onPaneFilterChange={handlePaneFilterChange}
            />
          )}
        />
      </main>
    </div>
  );
}
